#include "ws.rpc.h"
#include "ws.packer.h"
#include "ws.unpacker.h"
#include "ws.assembler.h"
#include "ws.server.h"

#include "../Headers/log.h"

#include <cstring>

TOB::WS::Assembler assembler = *(TOB::WS::Assembler::getInstance());

/**
 * Функция подготовки сервера к приему пакетов
 * @return token
 */
int * start_sending_1_svc(void * ptr, struct svc_req * svc) {
  static int respond;
  int token = assembler.newPacker();
  respond = token;
  TOB::Log::event("WS: New request.");
  return &respond;
}

/**
 * Функция приема пакета
 * @return (0 - успех, -1 - неудача)
 */
int * send_1_svc(package * pack, struct svc_req * svc) {
  int token = pack->token;
  static int ret;
  
  if (!(assembler.existPacker(token))) {
    ret = -1;
    return &ret;
  }
  assembler[token]->push(*pack);
  
  ret = 0;
  return &ret;
}

/**
 * Функция окончания приема пакета, и обработки полученных данных
 * @return (0 - успех, -1 - неудача)
 */
int * end_sending_1_svc(int * ptoken, struct svc_req * svc) {
  int token = *ptoken;
  static int ret;
  
  if (!(assembler.existPacker(token))) {
    ret = -1;
    return &ret;
  }
  TOB::WS::Unpacker* unpacker = NULL;
  try {
    unpacker = new TOB::WS::Unpacker(*(assembler[token]));
  } catch (TOB::WS::UnpackerException) {
    ret = -1;
    return &ret;
  }
  delete assembler[token];
  
  try {
    assembler.setLinkPackerByToken(TOB::WS::WebServer::ExecRequest(*unpacker), token);
  } catch (TOB::WS::WebServerException) {
    //ret = -1;
    //return &ret;
  }
  if (assembler[token] == NULL) {
    ret = -1;
    return &ret;
  }
  
  if (unpacker != NULL) {
    delete unpacker;
  }
  
  ret = 0;
  return &ret;
}

/**
 * Функция проверяет есть ли пакет для приема
 * @return количество не принятых пакетов (-1 - ошибка)
 */
int * ready_pack_1_svc(int * ptoken, struct svc_req * svc) {
  int token = *ptoken;
  
  static int ret = 0;
  
  if (assembler[token] == NULL) {
    ret = -1;
  }
  else {
    ret = assembler[token]->getCount();
    if (ret == 0) { 
      delete assembler[token];
      assembler.erase( assembler.find(token) );
      TOB::Log::event("WS: Request comlited.");
    }
  }
  
  return &ret;
}

/**
 * Функция приема пакета
 * @return пакет
 */
package * resive_1_svc(int * ptoken, struct svc_req * svc) {
  int token = *ptoken;
  
  static package ret;
  
  if (assembler[token] != NULL) {
    ret.token = (*assembler[token])[0].token;
    ret.length = (*assembler[token])[0].length;
    memcpy(ret.data, (*assembler[token])[0].data, (*assembler[token])[0].length);
    assembler[token]->erase(0);
  }
  
  return &ret;
}
